#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include <boost/algorithm/string.hpp>
#include <vector>
#include <unordered_map>
#include <sys/time.h>

class FileUtil
{
    public:
        //读取文件内容
        static bool ReadFile(const std::string& filename,std::string* content)
        {
            //1.清空content当中的内容
            content->clear();

            std::ifstream file(filename.c_str());
            if(!file.is_open())
                return false;
            //文件被打开了
            std::string line;
            while(std::getline(file,line))
            {
                (*content)+=line+"\n";
            }
            file.close();
            return true;
        }

        //往文件写入内容
        static bool WriteFile(const std::string& fileName,const std::string& data)
        {
            std::ofstream file(fileName.c_str());
            if(!file.is_open())
                return false;
            file.write(data.c_str(),data.size());
            file.close();
            return true;
        }
};

class StringUtil
{
    public:

        //分割字符串
        static void Split(const std::string& input,const std::string& split_char,std::vector<std::string>* output)
        {
            boost::split(*output,input,boost::is_any_of(split_char),boost::token_compress_off);
        }
};

class UrlUtil
{
    public:
        //解析返回的字符串编码
        static void anaBody(const std::string& body,std::unordered_map<std::string,std::string>* kv_body)
        {
            std::vector<std::string> body_vec;
            StringUtil::Split(body,"&",&body_vec);
            for(auto& i:body_vec)
            {
                std::vector<std::string> child_vec;
                StringUtil::Split(i,"=",&child_vec);
                if(child_vec.size()!=2)
                    continue;
                (*kv_body)[child_vec[0]]=UrlDecode(child_vec[1]);
            }
        }
        static unsigned char ToHex(unsigned char x)   
        {   
            return  x > 9 ? x + 55 : x + 48;   
        }  

        static unsigned char FromHex(unsigned char x)   
        {   
            unsigned char y;  
            if (x >= 'A' && x <= 'Z') y = x - 'A' + 10;  
            else if (x >= 'a' && x <= 'z') y = x - 'a' + 10;  
            else if (x >= '0' && x <= '9') y = x - '0';  
            else assert(0);  
            return y;  
        }  

        static std::string UrlEncode(const std::string& str)  
        {  
            std::string strTemp = "";  
            size_t length = str.length();  
            for (size_t i = 0; i < length; i++)  
            {  
                if (isalnum((unsigned char)str[i]) ||   
                        (str[i] == '-') ||  
                        (str[i] == '_') ||   
                        (str[i] == '.') ||   
                        (str[i] == '~'))  
                    strTemp += str[i];  
                else if (str[i] == ' ')  
                    strTemp += "+";  
                else  
                {  
                    strTemp += '%';  
                    strTemp += ToHex((unsigned char)str[i] >> 4);  
                    strTemp += ToHex((unsigned char)str[i] % 16);  
                }  
            }  
            return strTemp;  
        }  

        static std::string UrlDecode(const std::string& str)  
        {  
            std::string strTemp = "";  
            size_t length = str.length();  
            for (size_t i = 0; i < length; i++)  
            {  
                if (str[i] == '+') strTemp += ' ';  
                else if (str[i] == '%')  
                {  
                    assert(i + 2 < length);  
                    unsigned char high = FromHex((unsigned char)str[++i]);  
                    unsigned char low = FromHex((unsigned char)str[++i]);  
                    strTemp += high*16 + low;  
                }  
                else strTemp += str[i];  
            }  
            return strTemp;  
        }  
};

//获取时间戳
class TimeUtil
{
    public:
        static int64_t TimeStampMs()
        {
            struct timeval tv;
            gettimeofday(&tv,NULL);
            return tv.tv_sec+tv.tv_usec/1000;
        }
        //获取年月日
        static void GetTime(std::string* TimeStamp)
        {
            time_t st;
            time(&st);
            struct tm* t=localtime(&st);

            char buf[30]={0};
            snprintf(buf,sizeof(buf)-1,"%04d-%02d-%02d %02d:%02d:%02d",t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
            TimeStamp->assign(buf,strlen(buf));
        }
};


enum LogLevel
{
    INFO=0,
    WARNING,
    ERROR,
    FATAL,
    DEBUG
};

const char* Level[]=
{
    "INFO",
    "WARNING",
    "ERROR",
    "FATAL",
    "DEBUG"
};

//1.日志等级
//2.文件名称
//3.行号
//4.想要记录的日志内容
inline std::ostream& Log(LogLevel lev,const char* file,int line,const std::string& logMsg)
{
    std::string level=Level[lev];
    std::string TimeStamp;
    TimeUtil::GetTime(&TimeStamp);
    std::cout<<"["<<TimeStamp<<" "<<level<<" "<<file<<":"<<line<<"]"<<" "<<logMsg;
    return std::cout;
}

#define LOG(lev,msg) Log(lev,__FILE__,__LINE__,msg)
